home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / BBS_UTL / BOI200P / GETCMBBS.PAS < prev    next >
Pascal/Delphi Source File  |  1992-12-13  |  37KB  |  849 lines

  1. { $D-}  { Disable Debug Information }
  2. {$S-}  { Disable Stack Checking }
  3. {$V-}  { Disable String Checking }
  4.  
  5. Unit GetCmBBS;
  6. { Part of BBS Onliner Interface }
  7. { Copyright (C) 1990, 1992 Andrew J. Mead
  8.   All Rights Reserved. }
  9.  
  10. { Original version 7/1/90 }
  11. { Original release version 9/5/90 }
  12. { Original public release 12/15/90 }
  13. { history found in IOLIB.PAS }
  14.  
  15. INTERFACE
  16.  
  17. IMPLEMENTATION
  18.  
  19. Uses
  20.   boidecl,
  21.   doorlib,
  22.   iolib,
  23.   crt,
  24.   dos;
  25.  
  26. Type
  27.   IRQtype   = array [0..15] of byte;     { array of IRQ information }
  28.   portype   = array [0..3] of word;      { default port addressess  }
  29.   buffarr   = array [0..$FFF0] of byte;
  30.  
  31. Var
  32.   bi_char      : char;                   { standard input character    }
  33.   bi_minmax    : byte;                   { maximum time allowed        }
  34.   gc_exitfile  : pathstr;                { lets GC_EXIT find drop file }
  35.  
  36. Const
  37.   bi_timedone  : boolean = false; { remaining time figured }
  38.   bi_filedone  : boolean = false; { BBS file processed }
  39.   bi_hofdone   : boolean = false; { /y processed }
  40.   bi_lockcomm  : boolean = false; { /c processed }
  41.   bi_lockIRQ   : boolean = false; { /i processed }
  42.   bi_locklocal : boolean = false; { /l processed }
  43.   bi_lockname  : boolean = false; { /n processed }
  44.   bi_setlocal  : boolean = false; { BBS file says it is in local play }
  45.   bi_portarray : portype =        { default port addressess for Com1 - Com4 }
  46.       ($3F8,$2F8,$3E8,$2E8);
  47.   IRQvector : IRQtype =        { interrupt vectors for IRQs 0 - 15 }
  48.       ($08,$09,$0A,$0B,$0C,$0D,$0E,$0F,$70,$71,$72,$73,$74,$75,$76,$77);
  49.   IRQmask   : IRQtype =        { 8259A IRQ enabling masks-used in Async.Pas }
  50.       ($FE,$FD,$FB,$F7,$EF,$DF,$BF,$7F,$FB,$FB,$FB,$FB,$FB,$FB,$FB,$FB);
  51.    { Remember:  When using the cascade PIC, send the cascade mask (for IRQ2) }
  52.   IRQ2msk   : IRQtype =        { cascade 8259A masks for IRQ8..IRQ15 }
  53.       ($00,$00,$00,$00,$00,$00,$00,$00,$FE,$FD,$FB,$F7,$EF,$DF,$BF,$7F);
  54.  
  55.   IRQnum    : byte    = 4;     { default IRQ - Com1 Com3 }
  56.  
  57. Procedure GETCOMMAND;
  58.   var
  59.     gc_t        : text;        { user information text file handle }
  60.     gc_f        : file;        { user information byte file handle }
  61.     gc_buff     : ^buffarr;    { buffer for drop file }
  62.     buffsize    : word;        { size of gc_buff^ }
  63.     gc_fsize    : word;        { size of gc_f     }
  64.     gc_str      : string;      { working string   }
  65.     error       : word;        { Val conversion error value }
  66.     timetemp    : real;        { Second/Minute time conversion variable }
  67.     opchs       : string [2];  { Opus-CBCS Task Designation   }
  68.     gc_loop     : byte;        { command line processing loop }
  69.     spval       : byte;        { SetPort return value - (initialization check) }
  70.  
  71. { The next major release of the BOI will have a thorough reworking of the
  72.   error reporting section.  It will also contain optional activity logging
  73.   and other features.  I have working code from other software I've written,
  74.   but I haven't had time to port and test it.  I am welcome to suggestions
  75.   and comments at this time - AJM (Dec 1992) }
  76.  
  77.   Procedure SHOWERROR(  { indicate error in processing drop file }
  78.       param  : byte;      { internal error code }
  79.       passtr : string);   { additional information to display }
  80.     var s : text;       { errorlog file handle }
  81.  
  82.     Procedure WRITEERROR(   { write error to log file   }
  83.         outstr : string);     { string to write to file }
  84.  
  85.       begin {* GetCommand,ShowError,WriteError *}
  86.         WriteLn(s,DoorName);   { tell what door generated error }
  87.         Write(s,'Abnormal termination of program at ');
  88.         Write(s,boi_starttime[1]:1,':',boi_starttime[2]:1,':',
  89.             boi_starttime[3]:1,'  ');  { show time of error }
  90.         WriteLn(s,boi_startdate[2]:1,'/',boi_startdate[3]:1,'/',
  91.             boi_startdate[1]:1,'.');   { show date of error }
  92.         WriteLn(s,'ERROR ',param:0);
  93.         WriteLn(outstr);
  94.         WriteLn(s,outstr);
  95.         WriteLn(s)
  96.       end;  {* GetCommand,ShowError,WriteError *}
  97.  
  98.     begin  {* GetCommand,ShowError *}
  99.       ClrScr; { Use console device for output }
  100.       Assign(s,LogFile);  { open error log }
  101.       if Exist(LogFile) then
  102.           if OpenText(s,denywrite + writeonly,tappend) = 0 then else
  103.       else if OpenText(s,denywrite + writeonly,trewrite) = 0 then;
  104.       WriteLn(DoorName,' version ',Version,'.');
  105.       WriteLn('Copyright (C) 1990, 1992 Andrew J. Mead');
  106.       WriteLn('All Rights Reserved.');
  107.       WriteLn('Contact: POB 1155 Chapel Hill, NC 27514-1155');
  108.       WriteLn;
  109.       WriteLn('Abnormal termination of program:');
  110.       WriteLn;
  111.       WriteLn('ERROR ',param:0);
  112.       case param of
  113.            2 : WriteError('Unknown or incorrect argument on command line.');
  114.            3 : WriteError(passtr+' file format not supported yet.');
  115.            4 : WriteError(
  116.            'Unable to find '+passtr+'.  Check implementation or notify Sysop.');
  117.            5 : WriteError('Error in '+passtr+'.  Check implementation.');
  118.            7 : WriteError('Duplicate directives.');
  119.            8 : WriteError('Path/Filename for Hall of Fame is not valid.');
  120.            9 : WriteError(passtr+' is not a valid path.');
  121. {         10 : WriteError('Invalid port setting(s) in '+passtr+'.'); }
  122.           11 : WriteError('Invalid or missing numeric in /X:nn.');
  123.           12 : WriteError('Hall of Fame limit out of range, must be in 1-19.');
  124.           13 : WriteError(
  125.                   'Invalid or missing value in /C:n.  ''n'' should be 1-8');
  126.           16 : WriteError('/L can not be used with either /C or /I');
  127.           17 : WriteError('Invalid format in /I:i:nnnn.');
  128.           18 : WriteError(
  129.               passtr+' is not a valid Hexadecimal address in /I statement.');
  130.           19 : WriteError('Invalid numeric in /A:x.');
  131.           20 : WriteError('/A timeleft should be at least 5.');
  132.           31 : WriteError('Unable to find/initialize FOSSIL driver.')
  133.         end;
  134.       WriteLn;
  135.       WriteLn('Check ',InfoFile,' for proper installation of this program.');
  136.       WriteLn('Report error message to SysOp.');
  137.       WriteLn;
  138.       WriteLn('Error saved in ',LogFile,'.');
  139.       Delay(5000); { five second delay }
  140.       WriteLn('Now returning to BBS.');
  141.       Close(s);
  142.       Halt($FF) { abandon ship }
  143.     end;  {* GetCommand,ShowError *}
  144.  
  145.   Procedure SETGAMETIME(   { convert dropfile time into BOI time }
  146.       settime : word);       { time from drop file }
  147.  
  148.     begin {* GetCommand,SetGameTime *}
  149.       boi_gametime := settime;
  150.       boi_usetime := true;   { indicate that this IS a timed game }
  151.       if boi_gametime < 10 then
  152.           boi_gametime := 8      { give player at least 8 minutes }
  153.       else Dec(boi_gametime,2);  { save 2 minutes for housekeeping }
  154.       if bi_timedone then   { player gets lessor of /x and dropfile times }
  155.           boi_gametime := Min(boi_gametime,bi_minmax - 2);
  156.       boi_gametime := Min(boi_gametime,90)  { player gets no more than 90 mins }
  157.     end;  {* GetCommand,SetGameTime *}
  158.  
  159.   Procedure FINDDROPFILE(
  160.       var dropfile : pathstr);
  161.  
  162.     begin {* GetCommand,FindDropFile *}
  163.       if bi_filedone then { dropfile has already been processed }
  164.           ShowError(7,'')
  165.       else bi_filedone := true;
  166.       if Length(gc_str) > 2 then
  167.         begin
  168.           Delete(gc_str,1,2);
  169.           if gc_str[1] = ':' then Delete(gc_str,1,1);
  170.           if (Length(gc_str) > 0) and (
  171.               not (gc_str[Length(gc_str)] in [':','\'])) then
  172.               gc_str := gc_str + '\';
  173.           dropfile := gc_str + dropfile; { add path to file name }
  174.           if not Valid(dropfile) then { dropfilespec not valid DOS filespec }
  175.               ShowError(9,gc_str)
  176.         end;
  177.       if not Exist(dropfile) then { dropfile not found }
  178.           ShowError(4,dropfile)
  179.     end;  {* GetCommand,FindDropFile *}
  180.  
  181.   Procedure PROCESSTEXT(      { process BBS system text file for user info }
  182.       txt_file     : pathstr;   { name of BBS system file }
  183.       txt_usename  : boolean;   { username is in file indicator }
  184.       txt_usetime  : boolean;   { user time remaining is in file indicator }
  185.       txt_useplen  : boolean;   { user screen length is in file indicator }
  186.       txt_ismins   : boolean;   { user time remaining is in minutes indicator }
  187.       txt_nameline : byte;      { line at which users name is found }
  188.       txt_timeline : byte;      { line at which users time remaining is found }
  189.       txt_lineline : byte;      { line at which users screen length is found }
  190.       txt_comline  : byte;      { line at which the comport is listed }
  191.       txt_combyte  : byte;      { byte in comline that determines comport }
  192.       txt_extra    : byte);     { extra information for a given file - switch }
  193.  
  194.     Procedure RESTART(      { read a given line number from text file }
  195.         readline : byte);     { line to read }
  196.         { places the given lines information in gc_str }
  197.       var
  198.         rloop : byte;
  199.  
  200.       begin {* GetCommand,ProcessText,Restart *}
  201.         if OpenText(gc_t,denynone + read_only,treset) = 0 then; { reset file }
  202.         {$I-}
  203.         for rloop := 1 to readline do ReadLn(gc_t,gc_str);
  204.         {$I+}
  205.         if IOResult <> 0 then
  206.             ShowError(5,txt_file) { file too short }
  207.       end;  {* GetCommand,ProcessText,Restart *}
  208.  
  209.     Procedure DORBBS;
  210.     { get users last name, and append it to the first name }
  211.  
  212.       begin {* GetCommand,ProcessText,DoRBBS *}
  213.         Restart(8); { Get user's last name }
  214.         boi_username := boi_username + ' ' + gc_str
  215.       end;  {* GetCommand,ProcessText,DoRBBS *}
  216.  
  217.     Procedure DOWWIV;
  218.     { check to see if game is being played locally or from remote }
  219.     { get user's real name }
  220.  
  221.       begin {* GetCommand,ProcessText,DoWWIV *}
  222.         Restart(15);
  223.         CleanString(gc_str);
  224.         if (Length(gc_str) > 0) and (gc_str[1] = '0') then bi_setlocal := true;
  225.         Restart(3);
  226.         boi_usereal := true;
  227.         boi_realname := gc_str;
  228.         Restart(1);
  229.         boi_realname := '#'+ gc_str + ' ' + boi_realname
  230.       end;  {* GetCommand,ProcessText,DoWWIV *}
  231.  
  232.     Procedure DOSPITFIRE;
  233.     { get user's user number }
  234.  
  235.       begin {* GetCommand,ProcessText,DoSpitfire *}
  236.         Restart(1);
  237.         boi_usereal := true;
  238.         boi_realname := '#' + gc_str;
  239.         {* code from John Reid *}
  240.         Restart(5);
  241.         if gc_str[1] = '0' then bi_setlocal := true
  242.       end;  {* GetCommand,ProcessText,DoSpitfire *}
  243.  
  244.     Procedure DOWILDCAT; { CALLINFO.BBS }
  245.     { check to see if game is being played locally or from remote }
  246.  
  247.       begin {* GetCommand,ProcessText,DoWildCat *}
  248.         Restart(28);
  249.         if Pos('LOCAL',gc_str) > 0 then bi_setlocal := true
  250.       end;  {* GetCommand,ProcessText,DoWildCat *}
  251.  
  252.     Procedure DO2AM;
  253.       begin {* GetCommand,ProcessText,Do2AM *}
  254.         Restart(6); { Get user's last name }
  255.         boi_username := boi_username + ' ' + gc_str;
  256.         Restart(3);
  257.         boi_usereal := true;
  258.         boi_realname := gc_str
  259.       end;  {* GetCommand,ProcessText,Do2AM *}
  260.  
  261.     Procedure DOPHOENIX;
  262.       begin {* GetCommand,ProcessText,DoPhoenix *}
  263.         Restart(2);
  264.         if Pos('LOCAL',gc_str) > 0 then bi_setlocal := true
  265.       end;  {* GetCommand,ProcessText,DoPhoenix *}
  266.  
  267.     begin {* GetCommand,ProcessText *}
  268.       FindDropFile(txt_file); { verify dropfile }
  269.       Assign(gc_f,txt_file); { open as binary file to get file size }
  270.       if OpenFile(gc_f,1,denynone + read_only,treset) = 0 then;
  271.       buffsize := FileSize(gc_f);
  272.       Close(gc_f);           { close file }
  273.       GetMem(gc_buff,buffsize); { allocate buffer on heap }
  274.       Assign(gc_t,txt_file);
  275.       SetTextBuf(gc_t,gc_buff^,buffsize); { assign buffer to file handle }
  276.  
  277.       { get user's name }
  278.       if txt_usename then
  279.         begin
  280.           Restart(txt_nameline);
  281.           boi_usename := true;
  282.           boi_username := Copy(gc_str,1,39)
  283.         end
  284.       else boi_usename := false;
  285.  
  286.       { get user's time remaining }
  287.       if txt_usetime then
  288.         begin
  289.           Restart(txt_timeline);
  290.           CleanString(gc_str);
  291.           Val(gc_str,timetemp,error);
  292.           if error <> 0 then ShowError(5,txt_file); { error in conversion }
  293.           if txt_ismins then SetGameTime(Trunc(timetemp))
  294.           else SetGameTime(Trunc(timetemp/60.0)) { tranlate seconds to minutes }
  295.         end
  296.       else boi_usetime := false;
  297.  
  298.       { get user's screen size }
  299.       if txt_useplen then
  300.         begin
  301.           Restart(txt_lineline);
  302.           CleanString(gc_str);
  303.           Val(gc_str,boi_pagelength,error);
  304.           if error <> 0 then ShowError(5,txt_file); { error in conversion }
  305.           if boi_pagelength > 24 then { reserve one line for status line }
  306.               Dec(boi_pagelength)
  307.         end;
  308.  
  309.       { get communication's port / local play mode info }
  310.       if not (bi_lockcomm or bi_locklocal or bi_lockIRQ) then
  311.         begin
  312.           Restart(txt_comline);
  313.           case gc_str[txt_combyte] of
  314.               '0' : bi_setlocal := true; { COM0 == Local mode }
  315.               '1'..'4' :
  316.                 begin
  317.                   boi_local := false;
  318.                   if gc_str[txt_combyte] in ['2','4'] then IRQnum := 3;
  319.                   boi_portnum := Ord(gc_str[txt_combyte]) - Ord('1')
  320.                   { portnum is one less than commnum 0==COM1, 1==COM2, etc... }
  321.                 end
  322.             end
  323.         end;
  324.       case txt_extra of { some drop files need special processing }
  325.           1 : DoRBBS;
  326.           2 : DoWWIV;
  327.           3 : DoWildCat;
  328.           4 : Do2AM;
  329.           5 : DoPhoenix;
  330.           6 : DoSpitfire
  331.         end;
  332.       Close(gc_t); { close dropfile }
  333.       FreeMem(gc_buff,buffsize)  { release buffer's memory back to heap }
  334.     end;  {* GetCommand,ProcessText *}
  335.  
  336.   Procedure PROCESSFILE(     { process BBS system data file for user info }
  337.       bin_file    : pathstr;   { name of BBS system file }
  338.       bin_usename : boolean;   { username is in file indicator }
  339.       bin_usetime : boolean;   { user time remaining is in file indicator }
  340.       bin_useplen : boolean;   { user screen length is in file indicatior }
  341.       bin_ismins  : boolean;   { user time remaining is in minutes indicator }
  342.       bin_nameoff : word;      { username offset      }
  343.       bin_namesiz : byte;      { username string size }
  344.       bin_timeoff : word;      { user time offset     }
  345.       bin_lineoff : word;      { user screen length offset  }
  346.       bin_commoff : word;      { communication port offset  }
  347.       bin_local   : word;      { local mode indicator value }
  348.       bin_extra   : byte);     { extra processing switch    }
  349.  
  350.     Procedure DOOPUS114;
  351.     { get user's real name }
  352.       begin {* GetCommand,ProcessFile,DoOpus114 *}
  353.         Move(gc_buff^[0],boi_realname[1],36);
  354.         boi_realname[0] := Chr(36);
  355.         if Pos(#0,boi_realname) > 0 then
  356.             boi_realname[0] := Chr(Pos(#0,boi_realname) - 1)
  357.         else CleanString(boi_realname);
  358.         if Length(boi_realname) > 0 then
  359.             if (Length(boi_username) = 0) then
  360.                 boi_username := boi_realname
  361.             else boi_usereal := true
  362.       end;  {* GetCommand,ProcessFile,DoOpus114 *}
  363.  
  364.     begin {* GetCommand,ProcessFile *}
  365.       FindDropFile(bin_file); { verify dropfile }
  366.       gc_exitfile := bin_file;
  367.       Assign(gc_f,bin_file); { open dropfile }
  368.       if OpenFile(gc_f,1,denynone + read_only,treset) = 0 then;
  369.       buffsize := FileSize(gc_f);
  370.       GetMem(gc_buff,buffsize); { allocate dropfile sized buffer on heap }
  371.       BlockRead(gc_f,gc_buff^,buffsize,gc_fsize); { read file into buffer }
  372.       Close(gc_f); { close file, get data from buffer }
  373.  
  374.       { get user's name }
  375.       if bin_usename and not bi_lockname then
  376.         begin
  377.           Move(gc_buff^[bin_nameoff],boi_username[1],bin_namesiz);
  378.           boi_username[0] := Chr(bin_namesiz);
  379.           if Pos(#0,boi_username) > 0 then
  380.               boi_username[0] := Chr(Pos(#0,boi_username) - 1)
  381.           else CleanString(boi_username);
  382.           boi_usename := true
  383.         end
  384.       else boi_usename := false;
  385.  
  386.       { get user's time remaining }
  387.       if bin_usetime then
  388.         begin
  389.           if bin_ismins then { time is already in minutes }
  390.               Move(gc_buff^[bin_timeoff],boi_gametime,SizeOf(word))
  391.           else Move(gc_buff^[bin_timeoff],timetemp,SizeOf(real));
  392.           if bin_ismins then SetGameTime(boi_gametime)
  393.           else SetGameTime(Trunc(timetemp/60.0)) { convert seconds to minutes }
  394.         end
  395.       else boi_usetime := false;
  396.  
  397.       { get user's screen size }
  398.       if bin_useplen then
  399.         begin
  400.           Move(gc_buff^[bin_lineoff],boi_pagelength,1);
  401.           if bin_extra = 1 then Inc(boi_pagelength,2);
  402.           if boi_pagelength > 24 then Dec(boi_pagelength)
  403.         end;
  404.  
  405.       { get communication's port / local play info }
  406.       if not (bi_lockcomm or bi_locklocal or bi_lockIRQ) then
  407.         begin                      { get communications port }
  408.           if bin_extra = 1 then { Opus 1.14 processes differently }
  409.             begin
  410.               { local mode is indicated at another offset }
  411.               if (gc_buff^[bin_local] or gc_buff^[bin_local]) = 0 then
  412.                   bi_setlocal := true
  413.               else
  414.                 begin
  415.                   boi_local := false;
  416.                   if gc_buff^[bin_commoff] in [1,3] then { 1,3 == COM2,COM4 }
  417.                       IRQnum := 3;
  418.                   boi_portnum := gc_buff^[bin_commoff];
  419.                 end
  420.             end
  421.           else case Chr(gc_buff^[bin_commoff]) of
  422.               #0,'0','L' : bi_setlocal := true;
  423.               '1'..'4',#1..#4 :
  424.                 begin
  425.                   boi_local := false;
  426.                   if Chr(gc_buff^[bin_commoff]) in [#2,#4,'2','4'] then
  427.                       IRQnum := 3;
  428.                   if gc_buff^[bin_commoff] in [1..4] then
  429.                       boi_portnum := gc_buff^[bin_commoff] - 1
  430.                   else boi_portnum := gc_buff^[bin_commoff] - Ord('1')
  431.                 end
  432.             end
  433.         end;
  434.  
  435.       case bin_extra of { some dropfiles require additional processing }
  436.           1 : DoOpus114
  437.         end;
  438.       FreeMem(gc_buff,buffsize) { release dropfile buffer memory to heap }
  439.     end;  {* GetCommand,ProcessFile *}
  440.  
  441.   Procedure DoPCBoard12( { Process drop file from PCBoard 12.x and Auntie BBS }
  442.       pc_file : pathstr);  { name of drop file }
  443.  
  444.     var
  445.       pc_time : real;
  446.       pc_mask : array [1..6] of byte absolute pc_time;
  447.     { PC Board times are in seconds stored as 4 byte reals (QBasic I think) }
  448.     { they must be converted into Turbo Pascal 6 byte reals, before being   }
  449.     { converted into longint. }
  450.  
  451.     begin {* GetCommand,DoPCBoard12 *}
  452.       FindDropFile(pc_file);
  453.       Assign(gc_f,pc_file); { open dropfile }
  454.       if OpenFile(gc_f,1,denynone + read_only,treset) = 0 then;
  455.       buffsize := FileSize(gc_f);
  456.       GetMem(gc_buff,buffsize); { allocate dropfile sized buffer on heap }
  457.       BlockRead(gc_f,gc_buff^,buffsize,gc_fsize); { read drop file into buffer }
  458.       Close(gc_f); { close file, get info from buffer }
  459.  
  460.       {get user's name }
  461.       Move(gc_buff^[14],boi_username[1],25);
  462.       boi_username[0] := Chr(25);
  463.       if Pos(#0,boi_username) > 1 then
  464.           boi_username[0] := Chr(Pos(#0,boi_username) - 1)
  465.       else CleanString(boi_username);
  466.       boi_usename := true;
  467.  
  468.       { convert stored real format to Turbo Pascal real format }
  469.       pc_mask[1] := gc_buff^[79];
  470.       pc_mask[2] := $00;
  471.       pc_mask[3] := $00;
  472.       pc_mask[4] := gc_buff^[76];
  473.       pc_mask[5] := gc_buff^[77];
  474.       pc_mask[6] := gc_buff^[78];
  475.  
  476.       { get game time }
  477.       SetGameTime(Trunc(pc_time/60.0)); { covert real seconds to word minutes }
  478.  
  479.       { get communications port / local play information }
  480.       if not (bi_lockcomm or bi_locklocal or bi_lockIRQ) then
  481.           if gc_buff^[10] = ord('L') then bi_setlocal := true;
  482.       FreeMem(gc_buff,buffsize) { release buffer memory back to heap }
  483.     end;  {* GetCommand,DoPCBoard12 *}
  484.  
  485.   Procedure DOSEARCHLIGHT;
  486.   { This works not just with Searchlight BBS, but it indicates that all     }
  487.   { information will passed via command line. }
  488.  
  489.     begin {* GetCommand,DoSearchLight *}
  490.       if bi_filedone then { dropfile already processed }
  491.           ShowError(7,'')
  492.       else bi_filedone := true
  493.     end;  {* GetCommand,DoSearchLight *}
  494.  
  495.   Procedure GETCOMPORT;
  496.   { set communications port by command line directive }
  497.     begin {* GetCommand,GetComPort *}
  498.       bi_lockcomm := true;
  499.       if bi_locklocal then ShowError(16,''); { /C and /L are incompatible }
  500.       boi_local := false;
  501.       if (gc_str[Length(gc_str)] in ['1'..'8']) then
  502.           boi_portnum := Ord(gc_str[Length(gc_str)]) - Ord('1')
  503.       else ShowError(13,'');
  504.       if boi_portnum in [1,3] then IRQnum := 3; { COM2, COM4 }
  505.     end;  {* GetCommand,GetComPort *}
  506.  
  507.   Procedure GETIRQINFO;
  508.   { set IRQ and port information by command line directive }
  509.     var
  510.       IRQerror : word;
  511.  
  512.     begin {* GetIRQInfo *}
  513.       bi_lockIRQ := true;
  514.       if bi_locklocal then ShowError(16,''); { /I and /L are incompatible }
  515.       boi_local := false;
  516.       foss_init := foss_init OR $01; { turn FOSSIL checking off! }
  517.       Delete(gc_str,1,2);
  518.       if gc_str[1] = ':' then Delete(gc_str,1,1);
  519.       if UpCase(gc_str[1]) in ['0'..'9','A'..'F'] then
  520.         begin
  521.           IRQnum  := Hex(gc_str[1]);         { assign IRQ number }
  522.           boi_portint := IRQvector[IRQnum];  { get interrupt vector for IRQ }
  523.           boi_picmask := IRQmask[IRQnum];    { get interrupt mask for IRQ }
  524.           boi_cascade := gc_str[1] > '7';    { IRQ8..IRQ15 on cascade PIC }
  525.           boi_pic2msk := IRQ2msk[IRQnum];
  526.           Delete(gc_str,1,1);
  527.           if gc_str[1] = ':' then Delete(gc_str,1,1)
  528.           else ShowError(17,'') { Error in /I:i:nnnn format }
  529.         end
  530.       else ShowError(17,''); { Error in /I:i:nnnn format }
  531.       if Length(gc_str) <> 4 then ShowError(17,'');
  532.       Val('$' + gc_str,boi_portadd,IRQerror);
  533.       if IRQerror > 0 then ShowError(18,gc_str)
  534.     end;  {* GetIRQInfo *}
  535.  
  536.   Procedure GETHOFLIM;
  537.   { limit player Hall of Fame appearances }
  538.     var
  539.       error : word;
  540.  
  541.     begin {* GetCommand,GetHofLim *}
  542.       if Length(gc_str) < 3 then ShowError(2,'');
  543.       Delete(gc_str,1,2);
  544.       if gc_str[1] = ':' then Delete(gc_str,1,1);
  545.       Val(gc_str,boi_hoflim,error);
  546.       if error > 0 then ShowError(11,'');
  547.       if not (boi_hoflim in [1..19]) then ShowError(12,'')
  548.     end;  {* GetCommand,GetHofLim *}
  549.  
  550.   Procedure GETHOF;
  551.   { redirect text Hall of Fame output }
  552.     begin {* GetCommand,GetHOF *}
  553.       bi_hofdone := true;
  554.       if Length(gc_str) < 3 then ShowError(2,'');
  555.       Delete(gc_str,1,2);
  556.       if gc_str[1] = ':' then Delete(gc_str,1,1);
  557.       if (Pos('.',gc_str) = 0) then
  558.         begin
  559.           if (gc_str[Length(gc_str)] in [':','\']) then
  560.               gc_str := gc_str + TxtHOF
  561.           else gc_str := gc_str + '\' + TxtHOF
  562.         end;
  563.       if not Valid(gc_str) then ShowError(8,'')
  564.       else boi_texthof := gc_str
  565.     end;  {* GetCommand,GetHOF *}
  566.  
  567.   Procedure GETTIMELIMIT; { set maximum time limit }
  568.     begin {* GetCommand,GetTimeLimit *}
  569.       bi_timedone := true;
  570.       if Length(gc_str) < 3 then ShowError(2,'');
  571.       Delete(gc_str,1,2);
  572.       if gc_str[1] = ':' then Delete(gc_str,1,1);
  573.       Val(gc_str,bi_minmax,error);
  574.       if error <> 0 then ShowError(8,'');
  575.       if bi_filedone then boi_gametime := Min(boi_gametime,bi_minmax - 2)
  576.       else
  577.         begin
  578.           boi_usetime := true;
  579.           boi_gametime := Min(bi_minmax - 2,90)
  580.         end
  581.     end;  {* GetCommand,GetTimeLimit *}
  582.  
  583.   Procedure DOPORTS; { use default IRQ and port information for communications }
  584.     begin {* GetCommand,DoPorts *}
  585.       boi_portadd := bi_portarray[boi_portnum];
  586.       boi_portint := IRQvector[IRQnum];
  587.       boi_picmask := IRQmask[IRQnum]
  588.     end;  {* GetCommand,DoPorts *}
  589.  
  590.   Procedure GETAGAIN; { get multiple play parameters }
  591.     var
  592.       error : word;
  593.  
  594.     begin {* GetCommand,GetAgain *}
  595.       boi_replay := true;
  596.       Delete(gc_str,1,2);
  597.       if gc_str[1] = ':' then Delete(gc_str,1,1);
  598.       If Length(gc_str) > 0 then
  599.         begin
  600.           Val(gc_str,boi_againtime,error);
  601.           if error > 0 then ShowError(19,'');
  602.           if boi_againtime < 5 then { must be at least 5 minutes left }
  603.               ShowError(20,'')
  604.         end
  605.       else boi_againtime := 10 { default minimum time for replay }
  606.     end;  {* GetCommand,GetAgain *}
  607.  
  608.   Procedure GETNAME; { get user's name from command line }
  609.     var
  610.       gloop : byte;
  611.  
  612.     begin {* GetCommand,GetName *}
  613.       Delete(gc_str,1,2);
  614.       if gc_str[1] = ':' then Delete(gc_str,1,1);
  615.       if Length(gc_str) > 0 then
  616.         begin
  617.           bi_lockname := true;
  618.           boi_usename := true;
  619.           boi_username := gc_str;
  620.           { convert '_' (underscores) to ' ' (spaces) }
  621.           for gloop := 1 to Length(boi_username) do
  622.               if boi_username[gloop] = '_' then
  623.               boi_username[gloop] := ' '
  624.         end
  625.     end;  {* GetCommand,GetName *}
  626.  
  627. { slash '/' switches }
  628. {    active switches :  12 4567 9ABCD FGHI KLMNOPQRST VWXYZ }
  629. {  reserved switches : 0  3    8     E                      }
  630. { available switches :                    J          U      }
  631. {   program switches : +-][=.                               }
  632.  
  633. { dash '-' switches } { unused at this point }
  634. {    active switches :                                      }
  635. {  reserved switches :                                      }
  636. { available switches : 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ }
  637.  
  638.   begin {* GetCommand *}
  639.     boi_usetime  := false;       { default - no time limit }
  640.     boi_usename  := false;       { default - no user name }
  641.     boi_usereal  := false;       { default - only know alias }
  642.     boi_pagelength := 24;        { default - 24 line screen }
  643.     boi_timexp   := false;       { set time to not expired }
  644.     for gc_loop := 1 to ParamCount do
  645.       begin
  646.         gc_str := ParamStr(gc_loop);
  647.         if (gc_str[1] = '/') and (Length(gc_str) > 1) then
  648.             case UpCase(gc_str[2]) of
  649. {PCBoard12x}'1' : DoPCBoard12('PCBoard.Sys');
  650. {2 A.M.}    '2' : ProcessText('Jumper.Dat',  true,true,false,true,  5, 8, 0, 9,4,4);
  651. {Opus 1.13} '3' : ShowError(3,'Opus-CBCS 1.13 '); { no docs for Opus 1.13 }
  652. {WWIV,TG}   '4' : ProcessText('Chain.Txt',   true,true,true, false, 2,16,10,21,1,2);
  653. {RyBBS}     '5' : ProcessText('CurrUser.BBS',true,true,false,true,  1,13, 0, 6,1,0);
  654. {Spitfire}  '6' : ProcessText('SFDoors.Dat', true,true,false,true,  2, 7, 0, 6,1,6);
  655. {Auntie}    '7' : DoPCBoard12('Auntie.Sys');
  656. {Sapphire}  '8' : ShowError(3,'Sapphire BBS '); { no docs for Sapphire BBS }
  657. {SeachLight}'9' : DoSearchLight;
  658. {GT Power}  '0' : ShowError(3,'GT Power '); { no docs for CURRUSER.BBS }
  659. {DoorWay}   'D' : ProcessText('Door.Sys',    true,true,false,true,  1, 4, 0, 2,1,0);
  660. {Forum}     'F' : ProcessText('UserInfo.Txt',true,true,false,false, 1, 4, 0, 5,1,0);
  661. {Genesis}   'G' : ProcessText('CallInfo.BBS',true,true,true, true,  1, 5,23,25,1,3);
  662. {Phoenix}   'H' : ProcessText('Info.Txt',    true,true,false,true,  1, 7, 0, 3,1,5);
  663. {ModuleX}   'M' : ProcessText('Number.Txt',  true,true,false,false, 1, 4, 0, 5,1,0);
  664. {PCBoard14x}'P' :
  665.               begin
  666.                 ProcessFile('PCBoard.Sys', true,true,false,true ,84,25,109, 0,125,18,0);
  667.                 boi_dmode := df_pcb14x { extra processing needed with carrier loss }
  668.               end;
  669. {GAP,Force} 'S' : ProcessText('Door.Sys',    true,true,true, true, 10,19,21, 1,4,0);
  670. {-WildCat,VBBS,etc...}
  671. {UBBS}      'U' : ShowError(3,'UBBS '); { no docs for UBBS }
  672. {WildCat}   'W' : ProcessText('CallInfo.BBS',true,true,true, true,  1, 5,23,29,4,3);
  673. {Opus 1.14} 'O' :
  674.               begin
  675.                 if (Length(gc_str) > 3) and (UpCase(gc_str[3]) in ['0'..'9','A'..'F'])
  676.                     and (UpCase(gc_str[4]) in ['0'..'9','A'..'F']) then
  677.                   begin
  678.                     opchs := Copy(gc_str,3,2);
  679.                     Delete(gc_str,3,2);
  680.                     ProcessFile('LastUS'+opchs+'.Dat',true,true,true,true,104,32,1030,173,1026,1024,1)
  681.                   end
  682.                 else ProcessFile('LastUser.Dat',true,true,true,true,104,32,1030,173,1026,1024,1)
  683.               end;
  684. {EIS-PC}    'R' :
  685. {FoReM}       begin  { Get node number }
  686. {OLEcom}        if (length(gc_str) > 2) and (gc_str[3] in ['0'..'9']) then
  687. {QuickBBS}        begin
  688. {RBBS}              bi_char := gc_str[3];
  689. {Remote Access}     delete(gc_str,3,1);
  690. {TAG}               ProcessText('DorInfo'+bi_char+'.Def',true,true,false,true,7,12,0,4,4,1)
  691. {TP-Board}        end
  692.                 else ProcessText('DoorInfo.Def',true,true,false,true,7,12,0,4,4,1)
  693.               end;
  694.  
  695. {Local}     'L' : if bi_locklocal then ShowError(7,'') else bi_locklocal := true;
  696. {lockcomm}  'C' : if bi_lockcomm or bi_lockIRQ then ShowError(7,'')
  697.                 else if not bi_setlocal then GetComPort;
  698. {lockIRQ}   'I' : if bi_lockcomm or bi_lockIRQ then ShowError(7,'')
  699.                 else if not bi_setlocal then GetIRQInfo;
  700.  
  701. {doagain}   'A' : if boi_replay then ShowError(7,'') else GetAgain;
  702. {baudlock}  'B' : if boi_ctsrts then ShowError(7,'') else boi_ctsrts := true;
  703. {getname}   'N' : if bi_lockname then ShowError(7,'') else GetName;
  704. {checkcd}   'K' : if not boi_checkcd then ShowError(7,'') else boi_checkcd := false;
  705. {doquiet}   'Q' : if boi_quiet then ShowError(7,'') else boi_quiet := true;
  706. {hoflim}    'X' : if boi_hoflim < 20 then ShowError(7,'') else GetHofLim;
  707. {hofpath}   'Y' : if bi_hofdone then ShowError(7,'') else GetHOF;
  708. {timelimit} 'Z' : if bi_timedone then ShowError(7,'') else GetTimeLimit;
  709.           end
  710.         else if ProgramSet(gc_str[1]) then  { program defined symbols }
  711.           begin
  712.             case gc_str[1] of
  713.                 '+' : if boi_plusidx  = 0 then boi_plusidx  := gc_loop else ShowError(7,'');
  714.                 '-' : if boi_minusidx = 0 then boi_minusidx := gc_loop else ShowError(7,'');
  715.                 ']' : if boi_closeidx = 0 then boi_closeidx := gc_loop else ShowError(7,'');
  716.                 '[' : if boi_openidx  = 0 then boi_openidx  := gc_loop else ShowError(7,'');
  717.                 '=' : if boi_equalidx = 0 then boi_equalidx := gc_loop else ShowError(7,'');
  718.                 '.' : if boi_dotidx   = 0 then boi_dotidx   := gc_loop else ShowError(7,'')
  719.               end
  720.           end
  721.         else if UpCase(gc_str[1]) = 'F' then { FOSSIL kludge }
  722.           begin
  723.             if Pos('-',gc_str) > 0 then
  724.                 foss_init := foss_init OR $01  { do NOT check for FOSSIL }
  725.             else if Pos('+',gc_str) > 0 then
  726.                 foss_init := foss_init OR $02; { only user FOSSIL }
  727.             if Pos('@',gc_str) > 0 then
  728.                 foss_init := foss_init OR $04  { de-initialize FOSSIL when done}
  729.  
  730. {  foss_init                                   }
  731. {  lower bits hold precedence                  }
  732.  
  733. {  $01   1  Force No Fossil           F-       }
  734. {  $02   2  Force Fossil              F+       }
  735. {  $04   4  De-Init FOSSIL            F@       }
  736. {  $08   8  undefined                          }
  737. {  $10  16  reserved                           }
  738. {  $20  32  reserved                           }
  739. {  $40  64  reserved                           }
  740. {  $80 128  reserved                           }
  741.  
  742.           end
  743.         else if UpCase(gc_str[1]) = 'A' then { AVATAR/1 kludge }
  744.           begin {* kludge *}
  745.             if Pos('+',gc_str) > 0 then boi_allowavt := true
  746.           end   {* kludge *}
  747.         else ShowError(2,'')
  748.       end;
  749.     if bi_locklocal and (bi_lockcomm or bi_lockIRQ) then
  750.         ShowError(16,''); { can't have /L with either /C or /I }
  751.     if bi_locklocal or bi_setlocal then boi_local := true;
  752.     boi_echo := not boi_local;
  753.     if not (boi_local or bi_lockIRQ) then DoPorts; { get default IRQ info }
  754.     if not bi_hofdone then { put default text HOF in game's .EXE directory }
  755.         boi_texthof := boi_gamedir + TxtHOF;
  756.     if boi_usetime then { convert time remaining into timer ticks 18.2/second }
  757.         boi_ticks := longint(boi_gametime) * 1092; { 1092 ticks per minute }
  758.  
  759.     spval := SetPort; { attempt to initialize comm port }
  760.     if spval > 0 then { communications initialization failed }
  761.         ShowError(spval,'')
  762.   end;  {* GetCommand *}
  763.  
  764. Var
  765.   bi_nextexit : pointer;  { pointer to hold address of next Exit procedure }
  766.  
  767. {$F+}
  768. Procedure GCEXIT;
  769.   var
  770.     f        : file;     { file handle for post-processing }
  771.     exitbuff : ^buffarr; { buffer to hold drop file }
  772.     exitsize : word;     { size of drop file }
  773.  
  774.   begin {* GCExit *}
  775.     exitproc := bi_nextexit;
  776.     if (not boi_local) and boi_cdlost and (boi_dmode = df_pcb14x) then
  777.       begin
  778.         { fill PCBOARD.SYS after byte nine with spaces if carrier lost }
  779.         Assign(f,gc_exitfile); { open dropfile }
  780.         if OpenFile(f,1,denynone + read_only,treset) = 0 then;
  781.         exitsize := FileSize(f); { get file size }
  782.         GetMem(exitbuff,exitsize); { allocate dropfile sized buffer on heap }
  783.         BlockRead(f,exitbuff^,exitsize); { read file into buffer }
  784.         FillChar(exitbuff^[9],exitsize - 9,' '); { blank out data }
  785.         if OpenFile(f,1,denyall + writeonly,trewrite) = 0 then; { erase file }
  786.         BlockWrite(f,exitbuff^,exitsize); { write blanked file }
  787.         Close(f); { close file, get data from buffer }
  788.         FreeMem(exitbuff,exitsize) { release buffer's memory back to heap }
  789.       end
  790.   end;  {* GCExit *}
  791. {$F-}
  792.  
  793. begin {* uGetCmBBS *}
  794.   bi_nextexit := exitproc;
  795.   exitproc := @GCExit;
  796.   { LoadLanguage; stay tuned for future developements! }
  797.   GetCommand
  798. end.  {* uGetCmBBS *}
  799.  
  800. Text Data Files
  801.   BBS System      SynData File    type   Name  Real  Time  Line  Comm  Local
  802. x 2 A.M. BBS         Jumper.Dat   text    5+6    3     8m  ----   9,4  ----
  803. x DoorWay          2 Door.Sys     text      1  ----    4m  ----   2,1  ----
  804. x EIS-PC           3 DorInfo#.Def text    7+8  ----   12m  ----   4,4  ----
  805. x Force BBS        1 Door.Sys     text     10  ----   19m   21    1,4  ----
  806. x FoReM            3 DorInfo#.Def text    7+8  ----   12m  ----   4,4  ----
  807. x Forum            4 UserInfo.Txt text      1  ----    4s  ----   5,1   5,L
  808. x GAP              1 Door.Sys     text     10  ----   19m   21    1,4  ----
  809.   Genesis            CallInfo.BBS text      1  ----    5m   23    ???  28,L
  810. x GT               2 Door.Sys     text      1  ----    4m  ----   2,1  ----
  811. x ModuleX          4 Number.Txt   text      1  ----    4s  ----   5,1   5,L
  812. x OLEcom           3 DorInfo#.Def text    7+8  ----   12m  ----   4,4  ----
  813. x Phoenix            Info.BBS     text      1  ----    7m  ----   3,1   2,L
  814. x Quick BBS        3 DorInfo#.Def text    7+8  ----   12m  ----   4,4  ----
  815. x RBBS             3 DorInfo#.Def text    7+8  ----   12m  ----   4,4  ----
  816. x Remote Acces     3 DorInfo#.Def text    7+8  ----   12m  ----   4,4  ----
  817. x RyBBS              CurrUser.BBS text      1  ----   13m  ----   6,1  ----
  818. x Spitfire BBS       SFDoors.Dat  text      2  ----    7m  ----   6,1  ----
  819. x TAG              3 DorInfo#.Def text    7+8  ----   12m  ----   4,4  ----
  820. x TP-Board         3 DorInfo#.Def text    7+8  ----   12m  ----   4,4  ----
  821. x WildCat 2.x        CallInfo.BBS text      1  ----    5m   23   29,4  28,L
  822. x WildCat 3.x      1 Door.Sys     text     10  ----   19m   21    1,4  ----
  823. x WWIV               Chain.Txt    text      2    3    16s   10   21,1  15,0
  824. x Telegard         x Can emulate most of the above
  825.  
  826. Binary Data Files
  827.   BBS System      SynData File    type   Name  Real  Time  Line  Comm  Local
  828. - Auntie BBS       5 Auntie.Sys   b128   14n25 ----   76c  ----  ----  10,L
  829.   OPUS-CBCS 1.13     LastUser.BBS b128    0l   ----   ???  123   ????  ????
  830. - OPUS-CBCS 1.14     LastUsXX.Dat b     104n32 0n36 1030mw 173  1026w  ----
  831. - PCBoard 12.x     5 PCBoard.Sys  b128   14n25 ----   76c  ----  ----  10,L
  832. x PCBoard 14.x       PCBoard.Sys  b128   84n25 ----   61mw ----  125c  18,L
  833.                                                      110mw
  834.   Sapphire BBS       Sapphire.Dat b545    0l   ----   ???   87   ????  ????
  835.  
  836. Command Line Driven
  837. x Search Light BBS
  838.  
  839. x in use
  840. - beta stage
  841.  
  842. m minutes
  843. s seconds
  844.  
  845. r real
  846. i integer
  847. w word
  848. c char
  849.